package multithreading;

import java.util.Random;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class demon1 {
    private final static Random random = new Random();
    private static volatile long sum1 = 0;  // 偶数下标和
    private static volatile long sum2 = 0;  // 奇数下标和
    private static int[] generateRandomIntArray(int[] arr){

        for(int i=0; i<arr.length;i++){
            arr[i]=random.nextInt(1,100);
        }
        return arr;
    }

    private static void sum(int[] arr) throws InterruptedException {
        generateRandomIntArray(arr);
        Thread thread1 =new Thread(()->{
            for (int i = 0; i < arr.length; i+=2) {
                sum1+=arr[i];
            }
        });
        Thread thread2=new Thread(()->{
            for (int i = 1; i < arr.length; i+=2) {
                sum2+=arr[i];
            }
        });
        thread1.start();
        thread2.start();
        thread1.join();  // 等待线程1完成
        thread2.join();  // 等待线程2完成
        System.out.println(sum1+sum2);
    }
    public static void main1(String[] args) throws InterruptedException {
        int[] arr=new int[10000000];
        for(int i =0;i<10000000;i++){
            arr[i]=i+1;
        }
        Thread thread1=new Thread(()->{
            for(int i= 0;i<arr.length;i+=2){
                sum1+=arr[i];
            }
        });
        Thread thread2=new Thread(()->{
            for(int i=1;i<arr.length;i+=2){
                sum2+=arr[i];
            }
        });
        thread1.start();
        thread2.start();
        thread1.join();
        thread2.join();
        System.out.println("偶数下标:"+sum1);
        System.out.println("奇数下标:"+sum2);
    }




    private static final int ARRAY_LENGTH = 10_000_000;
    private static int[] array;

    //5种方式实现多线程案例

    private void generateRandomArray(){
        for (int i = 0; i < ARRAY_LENGTH; i++) {
            array[i]=random.nextInt(1,101);
        }
    }
    //lambda实现,不使用lambda实现则需要重写run方法
    private static void method0DirectlyUsingThread(){
        long startTime=System.currentTimeMillis();
        // 使用原子类存储结果
        AtomicLong evenSum = new AtomicLong(0);
        AtomicLong oddSum = new AtomicLong(0);
        Thread t3 =new Thread(){
            @Override
            public void run() {
                //这里写逻辑
            }
        };
        Thread t1 = new Thread(()->{
            long localSum = 0; // 局部变量累加，减少volatile变量访问次数
            for (int i = 0; i < array.length; i += 2) {
                localSum += array[i];
            }
            evenSum.set(localSum);
        });
        Thread t2=new Thread(()->{
            long localSum = 0;
            for (int i = 1; i < array.length; i+=2) {
                localSum+=array[i];
            }
            oddSum.set(localSum);
        });
        t1.start();
        t2.start();
        try {
            t1.join();
            t2.join();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        long endTime = System.currentTimeMillis();
        System.out.println("方法5 (使用Lambda表达式):");
        System.out.println("偶数下标和: " + evenSum.get());
        System.out.println("奇数下标和: " + oddSum.get());
        System.out.println("执行时间: " + (endTime - startTime) + " 毫秒\n");
    }
    //继承Thread类实现,还是使用lambda方式写
    private static void method1UsingThreadClass(){
        long startTime=System.currentTimeMillis();
        EvenSumThread evenSumThread=new EvenSumThread();
        OddSumThread oddSumThread=new OddSumThread();
        evenSumThread.start();
        oddSumThread.start();
        try {
            evenSumThread.join();
            oddSumThread.join();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        long endTime = System.currentTimeMillis();
        System.out.println("方法1 (继承Thread类):");
        System.out.println("偶数下标和: " + evenSumThread.getSum());
        System.out.println("奇数下标和: " + oddSumThread.getSum());
        System.out.println("执行时间: " + (endTime - startTime) + " 毫秒\n");
    }
    //静态内部类
    static class EvenSumThread extends Thread{
        private long sum=0;
        @Override
        public void run() {
            for (int i = 0; i < array.length; i+=2) {
                sum+=array[i];
            }
        }
        public long getSum(){
            return sum;
        }
    }
    static class OddSumThread extends Thread{
        private long sum=0;

        @Override
        public void run() {
            for(int i=1;i< array.length;i+=2){
                sum+=array[i];
            }
        }
        public long getSum(){
            return sum;
        }
    }




    //Runnable接口实现
    private static void method2UsingRunnable(){
        long startTime =System.currentTimeMillis();
        AtomicLong evenSum=new AtomicLong(0);
        AtomicLong oddSum=new AtomicLong(0);
        Thread t1=new Thread(new EvenSumRunnable(evenSum));
        Thread t2=new Thread(new OddSumRunnable(oddSum));
        t1.start();
        t2.start();
        try {
            t1.join();
            t2.join();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        long endTime=System.currentTimeMillis();
        System.out.println("方法2 (实现Runnable接口):");
        System.out.println("偶数下标和: " + evenSum.get());
        System.out.println("奇数下标和: " + oddSum.get());
        System.out.println("执行时间: " + (endTime - startTime) + " 毫秒\n");

    }
    static class EvenSumRunnable implements Runnable{
        private final AtomicLong sum;
        public EvenSumRunnable(AtomicLong sum){
            this.sum=sum;
        }
        @Override
        public void run() {
            for (int i = 0; i < array.length; i+=2) {
                sum.addAndGet(array[i]);
            }
        }
    }
    static class OddSumRunnable implements Runnable{
        private final AtomicLong sum;
        public OddSumRunnable(AtomicLong sum){
            this.sum=sum;
        }
        @Override
        public void run() {
            for (int i = 1; i < array.length; i+=2) {
                sum.addAndGet(array[i]);
            }
        }
    }




    // 方法3: 使用Callable和Future
    private static void method3UsingCallableFuture() throws ExecutionException, InterruptedException {
        long startTime = System.currentTimeMillis();
        Callable<Long> evenCallable = () ->{
            long sum =0;
            for (int i = 0; i < array.length; i+=2) {
                sum+=array[i];
            }
            return sum;
        };
        Callable<Long> oddCallable = () ->{
            long sum=0;
            for (int i = 1; i < array.length; i+=2) {
                sum+=array[i];
            }
            return sum;
        };
        FutureTask<Long> evenFuture =new FutureTask<>(evenCallable);
        FutureTask<Long> oddFuture =new FutureTask<>(oddCallable);
        new Thread(evenFuture).start();
        new Thread(oddFuture).start();
        //这里不需要添加等待,因为get方法会阻塞线程也就是主线程
        long evenSum= evenFuture.get();
        long oddSum = oddFuture.get();
        long endTime = System.currentTimeMillis();
        System.out.println("方法3 (使用Callable和Future):");
        System.out.println("偶数下标和: " + evenSum);
        System.out.println("奇数下标和: " + oddSum);
        System.out.println("执行时间: " + (endTime - startTime) + " 毫秒\n");
    }

    //线程池方式实现
    private static void method4UsingThreadPool(){
        long startTime = System.currentTimeMillis();
        ExecutorService executorService = Executors.newFixedThreadPool(2);
        Future<Long> evenFuture =executorService.submit(()->{
            long sum = 0;
            for (int i = 0; i < array.length; i+=2) {
                sum+=array[i];
            }
            return sum;
        });
        Future<Long> oddFuture=executorService.submit(()->{
            long sum=0;
            for (int i = 0; i < array.length; i+=2) {
                sum+=array[i];
            }
            return sum;
        });
        try {
            long evenSum =evenFuture.get();
            long oddSum = oddFuture.get();
            long endTime =System.currentTimeMillis();
            System.out.println("方法4(使用线程池)");
            System.out.println("偶数下标和: " + evenSum);
            System.out.println("奇数下标和: " + oddSum);
            System.out.println("执行时间: " + (endTime - startTime) + " 毫秒\n");
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } catch (ExecutionException e) {
            throw new RuntimeException(e);
        }

    }




    private static int count=0;
    private static final Object o=new Object();
    public static void main2(String[] args) throws InterruptedException {
        Thread thread=new Thread(()->{
            for (int i = 0; i < 10000; i++) {
                synchronized(o){
                    count++;
                }
            }
        });
       Thread thread1=new Thread(()->{
           for (int i = 0; i < 10000; i++) {
               synchronized(o){
                   count++;
               }
           }
       });
       thread.start();
       thread1.start();
       thread.join();
       thread1.join();
       System.out.println(count);
    }

    public static void main3(String[] args) throws InterruptedException {
        AtomicInteger atomicInteger=new AtomicInteger();
        Thread thread=new Thread(()->{
            for (int i = 0; i < 10000; i++) {
                atomicInteger.incrementAndGet();
            }
        });
        Thread thread1=new Thread(()->{
            for (int i = 0; i < 10000; i++) {
                atomicInteger.incrementAndGet();
            }
        });
        thread.start();
        thread1.start();
        thread.join();
        thread1.join();
        System.out.println(atomicInteger.get());
    }




    private static final Object o1=new Object();
    private static final Object o2=new Object();
    public static void main4(String[] args) {
        Thread thread1=new Thread(()->{
            synchronized (o1){
                System.out.println("线程1拿到o1这个锁");
                synchronized (o2){
                    System.out.println("线程1拿到o2这个锁");
                }
            }

        });
        Thread thread2=new Thread(()->{
            synchronized (o2){
                System.out.println("线程2拿到o2这个锁");
                synchronized (o1){
                    System.out.println("线程2拿到o这个锁");
                }
            }

        });
        thread1.start();
        thread2.start();
    }

    private static final Lock locker1=new ReentrantLock();
    private static final Lock locker2=new ReentrantLock();
    public static void main(String[] args) {
        Thread thread1=new Thread(()->{
            try{
                locker1.lock();
                System.out.println("线程1拿到loccker1");
                locker2.lock();
                System.out.println("线程1拿到locker2");
            }finally {
                locker2.unlock();
                locker1.unlock();
            }

        });
        Thread thread2=new Thread(()->{
            try{
                locker2.lock();
                System.out.println("线程2拿到loccker1");
                locker1.lock();
                System.out.println("线程2拿到locker2");
            }finally {
                locker1.unlock();
                locker2.unlock();
            }
        });
        thread1.start();
        thread2.start();
    }




}
